﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Threading;
using System.Windows.Threading;
using System.Diagnostics;

namespace a13_MTA_calcPrime
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool goOn = false;
        private long curPrime = 3;
        private Stopwatch stopWatch;

        private Thread workerThread;
        private int uiThreadId;

        public MainWindow()
        {
            InitializeComponent();

            stopWatch = new Stopwatch();

            //create the worker thread and start it.
            workerThread = new Thread(WorkerThreadEntry);
            //workerThread.IsBackground = true;
            workerThread.Start();
        }

        //the worker thread proc
        private void WorkerThreadEntry()
        {
            Debug.WriteLine("Worker thread start, threadId=" + Thread.CurrentThread.ManagedThreadId);

            //build msg loop
            Dispatcher.Run();

            Debug.WriteLine("worker thread exit, threadId=" + Thread.CurrentThread.ManagedThreadId);
        }



        private void StartOrStopCalc(object sender, RoutedEventArgs e)
        {
            //uiThreadId = Thread.CurrentThread.ManagedThreadId;

            if (goOn)
            {
                goOn = false;
                startOrStopBtn.Content = "Resume";
                Debug.WriteLine("Click to stop calc prime, threadId=" + Thread.CurrentThread.ManagedThreadId);
            }
            else
            {
                goOn = true;
                startOrStopBtn.Content = "Stop";

                Debug.WriteLine("Click to start calc prime, threadId=" + Thread.CurrentThread.ManagedThreadId);
                Dispatcher.FromThread(workerThread).BeginInvoke(DispatcherPriority.Normal, new Action(CheckNextPrime));
            }
        }

        private void UpdatePrimeUi(long bigPrimeNum, long elapsedMSec)
        {
            Debug.WriteLine("Update UI, threadId=" + Thread.CurrentThread.ManagedThreadId);
            bigPrime.Text = "Bigges prime: " + bigPrimeNum;
            elapsedTime.Text = "Elapsed time: " + elapsedMSec;

            if (goOn)
            {
                Debug.WriteLine("Trig next calc");
                //Dispatcher.FromThread(workerThread).BeginInvoke(DispatcherPriority.SystemIdle, new Action(CheckNextPrime));
                Dispatcher.FromThread(workerThread).BeginInvoke(DispatcherPriority.Normal, new Action(CheckNextPrime));
            }
        }

        private void CheckNextPrime()
        {
            Debug.WriteLine("Calc next prime, curPrime=" + curPrime + ", threadId=" + Thread.CurrentThread.ManagedThreadId);

            stopWatch.Start();

            bool notPrime = false;

            for (long i = 3; i <= Math.Sqrt(curPrime); i++)
            {
                if (curPrime % i == 0)
                {
                    // Set not a prime flag to true.
                    notPrime = true;
                    break;
                }
            }

            // If a prime number.
            if (!notPrime)
            {
                stopWatch.Stop();

                bigPrime.Dispatcher.BeginInvoke(new Action<long, long>(UpdatePrimeUi), curPrime, stopWatch.ElapsedMilliseconds);

                stopWatch.Reset();
            }
            else
            {
                //若不是prime, 则发起下一个check
                //之所以不直接计算到找到下一个prime为止,是为了保持workerThread可以及时检查退出标志.
                Dispatcher.FromThread(workerThread).BeginInvoke(DispatcherPriority.Normal, new Action(CheckNextPrime));
            }

            curPrime += 2;
        }


        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            //close the worker thread
            if (workerThread != null)
            {
                Dispatcher.FromThread(workerThread).InvokeShutdown();
                Debug.WriteLine("Close the worker thread");
            }
        }

    }
}
